﻿using MiniFox.Components;
using MiniFox.Scripting.Configurations;
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace MiniFox.Scripting
{
    /// <summary>
    /// 
    /// </summary>
    public static class ScriptEngine
    {
        const string EXPRESSION_SAMPLE = @"${{{0}}}";
        const string EXPRESSION_PATTERN = @"\$\{((?:.|\r?\n)+?)\}";
        const string FUNC_PATTERN = @"^[a-zA-Z]{1}\w*";
        const string ARGS_PATTERN = @"\(((?:.|\r?\n)+?)\)";
        /// <summary>
        /// 
        /// </summary>
        public static readonly Regex REG_EXPRESSION;
        /// <summary>
        /// 
        /// </summary>
        public static readonly Regex REG_FUNCTION;
        /// <summary>
        /// 
        /// </summary>
        public static readonly Regex REG_ARGUMENTS;

        static ScriptEngine()
        {
            REG_EXPRESSION = new Regex(EXPRESSION_PATTERN, RegexOptions.Compiled);
            REG_FUNCTION = new Regex(FUNC_PATTERN, RegexOptions.Compiled);
            REG_ARGUMENTS = new Regex(ARGS_PATTERN, RegexOptions.Compiled);
        }

        private static FunctionContainer _container;
        /// <summary>
        /// 
        /// </summary>
        public static FunctionContainer Container
        {
            get
            {
                lock (typeof(FunctionContainer))
                {
                    if (_container == null)
                    {
                        _container = ComponentFactory.GetComponent<FunctionContainer>();
                    }
                }
                return _container;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static string Resolve(this string input)
        {
            string result = REG_EXPRESSION.Replace(input, new MatchEvaluator(ReplaceMatch));
            
            //替换命令
            return result;
        }

        private static string ReplaceMatch(Match match)
        {
            var func_call = match.Groups[1].Value;
            Match match_func = REG_FUNCTION.Match(func_call);
            if (!match_func.Success) return string.Empty;
            var func_name = match_func.Groups[0].Value;
            //函数实例
            var function = Container.Functions[func_name];
            Match match_args = REG_ARGUMENTS.Match(func_call);
            List<object> parameters = new List<object>();
            if (match_args.Success)
            {
                var str_args = match_args.Groups[1].Value;
                string[] arguments = str_args.Split(',');
                foreach (var argument in arguments)
                {
                    parameters.Add(argument.Trim());
                }
            }
            //执行函数得到结果
            object val = function.Execute(parameters.ToArray());
            return val.ToString();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="functionName"></param>
        /// <returns></returns>
        public static string CreateFunctionExpression(string functionName)
        {
            if (string.IsNullOrWhiteSpace(functionName))
                return functionName;

            //return $"${{{functionName}}}";
            return string.Format(EXPRESSION_SAMPLE, functionName);
        }
    }
}
